﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace AkashaMemory
{
    class Mod
    {
        public Mod(string path, string mD5, string name)
        {
            Path = path;
            MD5 = mD5;
            Name = name;
        }

        public string Path { get; set; }
        public string MD5 { get; set; }
        public string Name { get; set; }

    }

    class ModList
    {
        public Mod[] Mods { get; set; }
        public int Num { get; set; }

        public ModList(Mod[] mods, int num)
        {
            Mods = mods;
            Num = num;
        }
    }

    static class ModsUpdate
    {
        static public ModList ModListLocal { get; set; }
        static public ModList ModListServer { get; set; }

        static public ModList LocalAbsent { get; set; }
        static public ModList LocalRedundancy { get; set; }

        static private string GetLocalMD5(string path)
        {
            FileStream fileStream = new FileStream(path, FileMode.Open);
            System.Security.Cryptography.MD5 mD5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] retVal = mD5.ComputeHash(fileStream);
            fileStream.Close();

            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                stringBuilder.Append(retVal[i].ToString("x2"));
            }
            return stringBuilder.ToString();
        }

        static public bool GenModsList()
        {
            try
            {
                string[] modsPath = Directory.GetFiles("./.minecraft/mods");

                List<Mod> mods = new List<Mod>();
                for (int i = 0; i < modsPath.Length; i++)
                {

                    mods.Add(new Mod(modsPath[i], GetLocalMD5(modsPath[i]), Path.GetFileName(modsPath[i])));
                }

                ModListLocal = new ModList(mods.ToArray(), mods.Count);

                return true;
            }
            catch
            {
                return false;
            }

        }

        static public bool GetModsList(string uRI)
        {
            try
            {
                XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
                xmlReaderSettings.IgnoreComments = true;
                XmlReader xmlReader = XmlReader.Create(uRI, xmlReaderSettings);
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(xmlReader);
                xmlReader.Close();

                List<Mod> mods = new List<Mod>();
                int modsNum = Convert.ToInt32(xmlDocument.SelectSingleNode("Mods").SelectSingleNode("ModsNum").InnerText);
                for (int i = 0; i < modsNum; i++)
                {
                    XmlNode modNode = xmlDocument.SelectSingleNode("Mods").SelectSingleNode("Mod" + i.ToString());
                    mods.Add(new Mod(
                        uRI + modNode.SelectSingleNode("Name").InnerText,
                        modNode.SelectSingleNode("MD5").InnerText,
                        modNode.SelectSingleNode("Name").InnerText));

                }
                ModListServer = new ModList(mods.ToArray(), mods.Count);

                return true;
            }
            catch
            {
                return false;
            }

        }

        static public void CompareMods()
        {
            List<string> serverModsMD5 = new List<string>();
            List<string> localModsMD5 = new List<string>();

            List<Mod> localRedundancy = new List<Mod>();
            List<Mod> localAbsent = new List<Mod>();

            foreach (Mod mod in ModListServer.Mods)
            {
                serverModsMD5.Add(mod.MD5);
            }
            foreach (Mod mod in ModListLocal.Mods)
            {
                localModsMD5.Add(mod.MD5);
            }

            foreach (string serverModMD5 in serverModsMD5)
            {
                //检查本地mod中是否存在服务器mod，不存在则本地缺失
                if (localModsMD5.IndexOf(serverModMD5) == -1)
                {
                    localAbsent.Add(ModListServer.Mods[serverModsMD5.IndexOf(serverModMD5)]);
                }
            }

            foreach (string localModMD5 in localModsMD5)
            {
                if (serverModsMD5.IndexOf(localModMD5) == -1)
                {
                    localRedundancy.Add(ModListLocal.Mods[localModsMD5.IndexOf(localModMD5)]);
                }
            }

            LocalAbsent = new ModList(localAbsent.ToArray(), localAbsent.Count);
            LocalRedundancy = new ModList(localRedundancy.ToArray(), localRedundancy.Count);
        }
    }

}
